#pragma once

#include <iostream>
#include <unistd.h>
#include <cerrno>
#include <cstring>
#include <sys/epoll.h>
#include "nocopy.hpp"

class Epoller : public nocopy
{
    static const int size = 128;

public:
    Epoller()
    {
        // 创建epoll模型
        _epfd = epoll_create(size);
        if (_epfd == -1)
        {
            std::cout << "epoll_create failed,errno:" << errno << ",err string:" << strerror(errno) << std::endl;
        }
        else
        {
            std::cout << "epoll_create success,epfd:" << _epfd << std::endl;
        }
    }

    // 将套接字添加到epoll模型的红黑树中
    int EpollUpdate(int oper, int sock, uint32_t event)
    {
        int n;
        // 如果是删除
        if (oper == EPOLL_CTL_DEL)
        {
            n = epoll_ctl(_epfd, oper, sock, nullptr);
            if (n != 0)
            {
                std::cout << "epoll delete failed" << std::endl;
            }
        }
        // 如果是添加进去,就要填充struct epoll_event
        else
        {
            struct epoll_event ev;
            ev.events = event; // 要关心的事件
            ev.data.fd = sock; // 后续使用的时候知道是哪个fd
            n = epoll_ctl(_epfd, oper, sock, &ev);
            if (n != 0)
            {
                std::cout << "epoll_add or epoll_mod failed" << std::endl;
            }
        }

        return n;
    }

    int EpollWait(struct epoll_event revs[], int num,int timeout)
    {
        int n = epoll_wait(_epfd, revs, num, timeout); // 阻塞等待
        return n;
    }

    ~Epoller()
    {
        if (_epfd > 0)
        {
            close(_epfd);
        }
    }

private:
    int _epfd;
    int _timeout{3000};
};